package com.tabnet.form;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.tabnet.beans.gammeproduit.PropositionGamme;
import com.tabnet.beans.personnes.Fournisseur;
import com.tabnet.beans.produit.Accessoire;
import com.tabnet.beans.produit.GammeProduit;
import com.tabnet.beans.produit.Option;
import com.tabnet.beans.produit.Produit;
import com.tabnet.dao.DAOAccessoire;
import com.tabnet.dao.DAOCategorie;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOOption;
import com.tabnet.dao.DAOPropositionGamme;

public class CreationPropositionForm {
	
	private static final String CHAMP_DESCP    = "descProp";
	private static final String CHAMP_DESCG    = "descGamme";
	private static final String CHAMP_NOMP     = "nomProduit";
	private static final String CHAMP_QTE      = "qte";
	private static final String CHAMP_PU       = "prixUnitaire";
	private static final String CHAMP_DESCPD   = "descProd";
	private static final String CHAMP_CAT      = "categorie";
	
	private static final String PARAM_COULEUR		= "OPT_C";
	private static final String PARAM_CAPACITE		= "OPT_D";
	private static final String PARAM_WIFI			= "OPT_W";
	
    private String              	resultat;
    private HashMap<String, String> erreurs        = new HashMap<String, String>();
    private DAOPropositionGamme     daoProp;
    private DAOCategorie 			daoCat;
    private DAOOption 				daoOption;
    private DAOAccessoire 			daoAccessoire;
	
    public CreationPropositionForm( DAOPropositionGamme daoProp, DAOCategorie daoCat, DAOOption daoOption, DAOAccessoire daoAccessoire) {
        this.daoProp = daoProp;
        this.daoCat = daoCat;
        this.daoOption = daoOption;
        this.daoAccessoire = daoAccessoire;
    }

    public HashMap<String, String> getErreurs() {
        return erreurs;
    }

    public String getResultat() {
        return resultat;
    }

    /**
     * Méthode qui créer une proposition à partir des données entrées par le fournisseur.
     * Si aucune erreur, la proposition est enregistrée dans la base de données
     * sinon le fournisseur doit corriger les erreurs.
     * @param request
     * @return prop la proposition
     * @throws DAOException 
     */
    public PropositionGamme creerProposition( HttpServletRequest request, Fournisseur fourn ) throws DAOException {
    	
    	// récupération des valeurs
        String descP = getValeurChamp( request, CHAMP_DESCP );
        String descG = getValeurChamp( request, CHAMP_DESCG );
        String nomP = getValeurChamp( request, CHAMP_NOMP );
        String qte = getValeurChamp( request, CHAMP_QTE );
        String pu = getValeurChamp( request, CHAMP_PU );
        String descPd = getValeurChamp( request, CHAMP_DESCPD );
        String categorie = getValeurChamp( request, CHAMP_CAT );
        String color = getValeurParametre(request, PARAM_COULEUR);
        String capacity = getValeurParametre(request, PARAM_CAPACITE);
        boolean wireless = getValeurParametreBoolean(request, PARAM_WIFI);
        
        // récupération des accessoires
        Map<String, Accessoire> lesAccessoires = daoAccessoire.listerAccessoire();
    	Map<String, Accessoire> mapSelect = new HashMap<String, Accessoire>();
    	
    	for(Accessoire oAccessoire : lesAccessoires.values()){
    		if(request.getParameter(oAccessoire.getRef()) != null){
    			mapSelect.put(oAccessoire.getRef(), oAccessoire);
    		}
    	}

        // création des objets
    	PropositionGamme prop = new PropositionGamme();
    	GammeProduit gamme = new GammeProduit();
    	Produit prod = new Produit();
    	
    	prop.set_fournisseur(fourn);
    	prop.setGammeProposer(gamme);
    	gamme.setProduitG(prod);
    	
    	// les options
    	Map<String, Option> lesOptions = daoOption.listerOption();
    	Map<String, Option> newOptions = new HashMap<String, Option>();
    	prod.setLstOptionP(lesOptions);
    	
        this.traiterCouleur(color, lesOptions.get(PARAM_COULEUR), newOptions);
        this.traiterCapaciter(capacity, lesOptions.get(PARAM_CAPACITE), newOptions);
        this.traiterWifi(wireless, lesOptions.get(PARAM_WIFI), newOptions);
        
        prod.setLstOptionP(newOptions);
        prod.setLstAccessoireP(mapSelect);

        // les tests de validation des données
        traiterDescP(descP,prop);
        traiterDescG(descG,prop);
        traiterNomP(nomP,prop);
        traiterQte(qte,prop);
        traiterPu(pu,prop);
        traiterDescPd(descPd,prop);
        traiterCategorie(categorie,prop);

        try {
            if ( erreurs.isEmpty() ) {
            	daoProp.addPropositionGamme(prop);
                resultat = "Succès de la création de la proposition.";
            } else {
            	resultat = "Échec de la création de la proposition.";
            }
        } catch ( DAOException e ) {
            setErreur( "imprévu", "Erreur imprévue lors de la création." );
            resultat = "Échec de la création de la proposition : une erreur imprévue est survenue, merci de réessayer dans quelques instants.";
            e.printStackTrace();
        }

        return prop;
    }
    
    // les traitements
    /**
     * <p>Procédure traiterCouleur<br />
     * Contrôle la couleur d'un produit commander</p>
     * @param pCouleur: la couleur selectionner
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterCouleur(String pCouleur, Option pOption , Map<String, Option> pOptions) {
    	if(pCouleur != null && pCouleur.length() != 0 && pCouleur != "Noir"){
    		Option oOption = pOption;
    		int i = 0;
    		String[] tabOption = pOption.getDescription().split("\\|");            
            
    		for(i = 0; i < tabOption.length; i++){
    			if(tabOption[i].equals(pCouleur))
    				break;
    		}
    		oOption.setChoix(i);
    		oOption.setDescription(pCouleur);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    /**
     * <p>Procédure traiterCapaciter<br />
     * Contrôle la capacitée d'un produit commander</p>
     * @param pCapacite: la capacite selectionner
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterCapaciter(String pCapacite, Option pOption , Map<String, Option> pOptions) {
    	if(pCapacite != null && pCapacite.length() != 0 && pCapacite != "16Go"){
    		Option oOption = pOption;
    		int i = 0;
    		String[] tabOption = pOption.getDescription().split("\\|");
    		
    		for(i = 0; i < tabOption.length; i++){
    			if(tabOption[i].equals(pCapacite))
    				break;
    		}
    		oOption.setChoix(i);
    		oOption.setDescription(pCapacite);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    /**
     * <p>Procédure traiterCapaciter<br />
     * Contrôle le Wifi/3G d'un produit commander</p>
     * @param pWifi: vrai si avec Wifi/3G
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterWifi(boolean pWifi, Option pOption , Map<String, Option> pOptions) {
    	if(pWifi){
    		Option oOption = pOption;
    		oOption.setDescription("Avec 3G");
    		oOption.setChoix(1);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    /**
     * <p>Fonction static getValeurParametre<br />
     * Utilitaire qui retourne null si un paramètre est vide, et son
     * contenu sinon.</p>
     * @param request : objet HttpServletRequest
     * @param nomChamp : nom du champ
     * @return la valeur du champ
     */
    private static String getValeurParametre( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 ) {
            return null;
        } else {
            return valeur;
        }
    }
    
    /**
     * <p>Fonction getValeurParametre<br />
     * Utilitaire qui retourne null si un paramètre est vide, et son
     * contenu sinon.</p>
     * @param request : objet HttpServletRequest
     * @param nomChamp : nom du champ
     * @return la valeur du champ
     */
    private boolean getValeurParametreBoolean( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0) 
            return false;
        
        if (valeur.equals("on"))
            return true;
        
        return false;
    }
    

    private void traiterDescP( String descP, PropositionGamme prop ) {
        try {
            validationDescP( descP );
        } catch ( Exception e ) {
            setErreur( CHAMP_DESCP, e.getMessage() );
        }
        prop.setDescription( descP );
    }
    
    private void traiterDescG( String descG, PropositionGamme prop ) {
        try {
            validationDescG( descG );
        } catch ( Exception e ) {
            setErreur( CHAMP_DESCG, e.getMessage() );
        }
        prop.getGammeProposer().setDescription( descG );
    }
    
    private void traiterNomP( String nomP, PropositionGamme prop ) {
        try {
            validationNomP( nomP );
        } catch ( Exception e ) {
            setErreur( CHAMP_NOMP, e.getMessage() );
        }
        prop.getGammeProposer().getProduitG().set_nomP( nomP );
    }
    
    private void traiterQte( String qte, PropositionGamme prop ) {
        try {
            validationQte( qte );
        } catch ( Exception e ) {
            setErreur( CHAMP_QTE, e.getMessage() );
        }
        prop.getGammeProposer().getProduitG().set_qteQtock(Integer.parseInt(qte));
        prop.getGammeProposer().setQteStockP(Integer.parseInt(qte));
    }
    
    private void traiterPu( String pu, PropositionGamme prop ) {
        try {
            validationPu( pu );
        } catch ( Exception e ) {
            setErreur( CHAMP_PU, e.getMessage() );
        }
        prop.getGammeProposer().getProduitG().setPuP(Double.parseDouble(pu));
    }
    
    private void traiterDescPd( String descPd, PropositionGamme prop ) {
        try {
            validationDescPd( descPd );
        } catch ( Exception e ) {
            setErreur( CHAMP_DESCPD, e.getMessage() );
        }
        prop.getGammeProposer().getProduitG().setDescription( descPd );
    }
    
    private void traiterCategorie( String categorie, PropositionGamme prop ) throws DAOException {
        prop.getGammeProposer().getProduitG().setCategorieP(daoCat.trouverCategorie(categorie));
    }
    
    // les validations
    private void validationDescP( String DescP ) throws FormValidationException, DAOException {
    	if ( DescP == null ) {
    		throw new FormValidationException( "Merci d'entrer une description." );
    	}
    }
    
    private void validationDescPd( String DescPd ) throws FormValidationException, DAOException {
    	if ( DescPd == null ) {
    		throw new FormValidationException( "Merci d'entrer une description." );
    	}
    }    
    private void validationDescG( String DescG ) throws FormValidationException, DAOException {
    	if ( DescG == null ) {
    		throw new FormValidationException( "Merci d'entrer une description." );
    	}
    }
    
    private void validationNomP( String nomP ) throws FormValidationException, DAOException {
    	if ( nomP != null ) {
            if ( nomP.length() < 2 ) {
                throw new FormValidationException( "Le nom du produit doit contenir au moins 2 caractères." );
            }
        } else {
            throw new FormValidationException( "Merci d'entrer un nom de produit." );
        }
    }
    
    private void validationPu( String pu ) throws FormValidationException, DAOException {
    	if ( pu == null ) {
            throw new FormValidationException( "Merci d'entrer un prix unitaire." );
        }
    }
    
    private void validationQte( String qte ) throws FormValidationException, DAOException {
    	if ( qte == null ) {
            throw new FormValidationException( "Merci d'entrer une quantité." );
        }
    }
    
    /*
     * Ajoute un message correspondant au champ spécifié à la map des erreurs.
     */
    private void setErreur( String champ, String message ) {
        erreurs.put( champ, message );
    }

    private static String getValeurChamp( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 ) {
            return null;
        } else {
            return valeur;
        }
    }
}
